// Copyright  2004-2008 Backplane Ltd.
//
// This file is part of Ubiquity formsPlayer
//
// Ubiquity formsPlayer is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3 of the License, or (at your
// option) any later version.
//
// Ubiquity formsPlayer is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License
// along with Ubiquity formsPlayer If not, see <http://www.gnu.org/licenses/>.
//	
//
//   Purpose:  Definition of CXFormsXFormsElement.
//   $Id$


// XFormsXFormsElement.h: Definition of the XFormsXFormsElement class
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_XFORMSXFORMSELEMENT_H__F6990E5B_034E_4979_94DD_B7F8BC7EB56E__INCLUDED_)
#define AFX_XFORMSXFORMSELEMENT_H__F6990E5B_034E_4979_94DD_B7F8BC7EB56E__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "resource.h"       // main symbols

#include "inetFunc.h"

#include "dom3core.h"

#include "idResolver.h"
#include <DOM3XPath.h>
#include "actionload.h"
#include "XFormsConfig.h"
class CUIImplRepository;
#include <vector>

#include "ErrorReportAction.h"

#include "TempDocImpl.h"
#include <ActiveScript.h>
#include <map>
#include <list>
#include "IPotentiallyAsynchronousAction.h"
#include "xforms.h"
#include "IValueElementStringGenerator.h"
#include "TabletPCUtil.h"
#include "EventSinkHandler.h"
#include "DeletionListener.h"
#include <DOM3XPath.h>
typedef std::map<CComBSTR, SAFEARRAY *> CMapCComBSTRToSafeArray;
typedef std::pair<CComBSTR,SAFEARRAY *> CComBSTRSafeArrayPair;
typedef std::list<CComBSTR> CComBSTRList;

//#include "events.h"
/**/
/////////////////////////////////////////////////////////////////////////////
// XFormsXFormsElement

class CImpl;
class CImplCase;
class CImplModel;
class CImplRepeat;
class CImplSubmitInfo;
class CEventSink;
class CXFormsXPathFunctions;
class CMessageDialog;
class CMSHTMLCSS3Handler;
struct IXFormsXPathFunctions;
class CFormControl;
class CImplGroup;
class CTempDocImpl;
class CDocumentImplementationHasFeature;
class CDocumentImplementationGetFeature;
class CDocumentEventCreateEvent;
class CImplNodeBinding;
typedef  std::list<CFormControl *> CFormControlList;
typedef  std::list<IPotentiallyAsynchronousAction *> CAsyncRunnerList;


typedef std::list<IDeletionListener*> CListOfDeletionListeners;

class CXFormsXFormsElement:
	public IEventSinkHandler
{

public:

	CXFormsXFormsElement(IHTMLDocument2 * pDoc);
	virtual ~CXFormsXFormsElement();

	void deleteControl(CFormControl * pControl);
	HRESULT GetValueElementString(BSTR * pbsValueElement);
	CComQIPtr<IHTMLPopup> m_pPop;
	/*
	 * These events are not defined in XForms, but it probably should be
	 */

	STDMETHOD(onload)(void);

	//XForms actions

	HRESULT dispatch(BSTR sName,BSTR sTarget,bool bBubbles,bool bCancelable);

	
	STDMETHOD(loadURI)(BSTR sHref, CImplActionLoadURI::EXlinkShow eShow);
	HRESULT refresh();
	HRESULT recalculate();
	HRESULT revalidate();
	STDMETHOD(submitInstance)(BSTR sId);
	//TODO the following requires in-situ id resolution,
	// it is  currently OK where they are, but may be better suited
	//	to being run in the invoke method that used to call them
	HRESULT resetInstance(BSTR sModel);

	// functions for maintaining and accessing m_bFatalErrorEncountered
	inline bool canContinue() const;

	//TODO: make private, implement a readystate method rather than several
	//	isDocument...() methods.
	bool m_bDocumentInitialised;
	CList<CImplGroup *,CImplGroup *> m_IterationsToDelete;	
	//moves the object referring to an open dialog between the two lists
	void onCloseDialog(CMessageDialog* pDlg);

	//if a control is destroyed early, this removes it from the list
	//	of controls to destroy to prevent overdeletion.
	HRESULT RemoveFormControl(CFormControl * pControl);
	

	HRESULT rebuild(bool bForceRebuild = false);
	
	HRESULT getCSS(BSTR * retVal, long * plLen) const;
	HRESULT LoadStylesheetCollectionIntoString(IHTMLStyleSheetsCollection * pColl) const;

	CIdResolver m_IdResolver;
	STDMETHOD(getRepeat)(const BSTR sId, CImplRepeat** ppRepeat);

	//model cannot occur in any scope other than top-level
	//	these methods therefore are kept here instead of 
	//	moving to CIdResolver.
	//	submission and instance are  children of model,
	//	so maybe should be moved to reflect that, but since ther
	//	is no scope that the model has other than document-level,
	//	there is no point.
	HRESULT AddSubmission(CImplSubmitInfo * pSubmitInfo);
	STDMETHOD(getSubmitInfo)(const BSTR sId, CImplSubmitInfo*& ppSubmitInfo) const;
	//maintenence of the model list and pending model count.
	void AddModel(CImplModel * pModel);
	HRESULT getInstance(BSTR InstanceId,CImplInstance *& pInstance);
	//<summary>
	//	Adds an instance to the form-global instance collection, to be returned by globalInstance, keyed on its id.
	//</summary>
	//<param name="pInstance">Pointer to an instance object to add to the collection</param>
	//<returns>
	//	S_OK if the instance was successfully added<br/>
	//	S_FALSE if the instance had no id, or the id was ""
	//	FP_E_DUPLICATE_INSTANCE if an instance of the same ID has already been added to the map.
	//</returns>
	HRESULT AddInstance(CImplInstance * pInstance);
	CMapStringToPtr m_Binds;
	//The following two are not const as they can raise fatal exceptions
	STDMETHOD(getBind)(const BSTR sId, CImplBind*& ppBind);
	STDMETHOD(getModel)(const BSTR sId, CImplModel*& ppModel); 
	//<summary>
	//	finds a model, given an instance document
	//</summary>
	//<param name="pUnkDocument">An instance docuement in the model</param>
	//<param name="ppModel">retval to store the model</param>
	//<returns>S_OK if a model was found, S_FALSE if it wasn't</returns>
	STDMETHOD(getModel)(IUnknown * pUnkDocument, CImplModel*& ppModel) const;


	//kept public so that controls can delete themselves from the orphan 
	// list if they are deleted by any other means.
	// Bug 836 - Change m_UndisplaidOrphans & m_Orphans to improve performance
	CMap<CFormControl*, CFormControl*, CFormControl*, CFormControl*> m_Orphans;//list to hold unbound form controls
	CMap<CFormControl*, CFormControl*, CFormControl*, CFormControl*> m_UndisplaidOrphans;//list to hold unbound form controls until they have been displaid

	//list to hold nodeBindings that could not find a model/bind
	//	and so could not complete init()
	CList<CImplNodeBinding*, CImplNodeBinding*> m_lstInitPending;

	CComBSTR m_sCurrentURL;
	
	//This is the namspace declaration located at the top of
	//	the HTML document, along with a cache of its length.
	//	Set in serializeNamespaces.
	mutable CComBSTR m_sNamespaceDeclaration;
	mutable long m_lNamespaceDeclaration;

	//This is a set of import processing instructions
	//	to pass to viewlinked documents to allow formsplayer to work
	//	in nested forms. (with its cached length)
	//	Set in serializeNamespaces.
	mutable CString m_sImportDirectives;
	mutable long m_lImportDirectives;

	CString m_sDefaultNamespacePrefix;
	//called when a control receives focus
	void onChangeFocus(CFormControl * pControl);

	inline void onElementEncountered();
	inline void onElementComplete();
//displaying dialogs etc. to the user
	void reportError(const char* sError = 0 , const long lErrorCode=0);
	void reportException(const char* sError = 0 , const long lErrorCode=0);

	HRESULT GetInlineSchema(BSTR bsURL,IXMLDOMDocument2 ** pDoc);
	CMapStringToPtr m_mapInlineSchemata;
	HRESULT AddInlineSchema(BSTR sSchemaId,BSTR sSchemaText,IXMLDOMDocument ** ppSchemaDoc);
	void DeregisterControlContainer(IUnknown* pUnk);
	HRESULT GetParentImpl(IUnknown * pKey, CImpl * * ppParent);
	void RegisterControlContainer(CImpl * pContainer,IUnknown * pKey );
	HRESULT GetNSResolver(IXPathNSResolver ** pResolver);
	void RemoveModel(CImplModel * pMod);
	HRESULT Remove(const BSTR sId);
	bool StopAddingControls();
	inline void StartAddingControls();
	inline bool isDocumentComplete() const;
	//This is to allow Xpath functions to resolve identifiers
	//	in scope for functions such as index()
	//	This is a bit of a fudge, as it should be passed in
	//Always set to NULL after use.  E_FAIL is returned on
	//	attempting to set it if it is already set.
	inline HRESULT putXPathIdentityResolver(CIdResolver * pResolver);
	
	HRESULT getFunctionLibrary(BSTR sURI, IDispatch **ppDisp) const;

	HRESULT GetHostDocument(IHTMLDocument4 ** pDoc);
	// Displays any orphans that are pending initialisation.
	HRESULT showNewOrphans(void);

	// Populates the string with the UIWrapper.
	inline HRESULT getUIWrapper(BSTR * pszWrapper);
	inline int getUIWrapperLen();

	static void insertResourceLocation(CStringW & sFormatString, bool bEscapeSlashes);
	HRESULT getUIChunk(BSTR m_sControlName,SAFEARRAY ** sfArray);
	HRESULT addUIChunk(BSTR m_sControlName,SAFEARRAY * sfArray);
	//Tests whether the form is operating within a frameset.
	HRESULT IsOperatingWithinFrameset( bool & bResult) const;
	long m_lFormKey;
	// adds branding to a form.
	//void brandForm();
	inline CMapStringToPtr* getModelList(void);
	inline CMapPtrToPtr* getControlContainers(void);
	void modelConstructDone(CImplModel * pModel);
	//<summary>sets the current XPath evaluation context</summary>
	void CXFormsXFormsElement::PushCurrentXPathContext(CNode * pContextInfo,CImplModel * pModel);
	void CXFormsXFormsElement::PopCurrentXPathContext();

	void AddAsyncRunner(IPotentiallyAsynchronousAction*pRunner);
	void RemoveAsyncRunner(IPotentiallyAsynchronousAction*pRunner);
	void AddPendingRepeat(BSTR s);
	bool IsPendingRepeat(const BSTR s)const;
	// adds a reference linking an XML document to a model into the approproate list.
	void SetModelDocument(CImplModel * pModel , IUnknown * pUnkDocument);
	void RemoveModelDocument(IUnknown * pUnkDocument);
	// Superceded by bug 267...
	//inline bool BrandingRequired(void) const;
	bool IsRepeatBeingWaitedFor(wchar_t *lpwszRepeat, int &nRepeats, bool bClear = false);
	// <summary>calls RRR functions on all models where needed</summary>
	HRESULT RunDeferredUpdate(void);

	CComPtr<IScriptEngine> m_pSelect1MinimalLibrary;
	CComPtr<IDispatch> m_pSelect1MinimalLibraryDispatch;
	// <summary>returns a string used to wrap repeat iterations using the current namespace declarations.  If none yet exists, creates one and returns it.</summary>
	BSTR GetRepeatIterationWrapper(void);
	// <summary>reports an exception from GetErrorInfo</summary>
	//<param name="hr">HRESULT  of the exception to report</param>
	void reportException(HRESULT hr);
	
	//<summary>reports a non-blocking error from GetErrorInfo</summary>
	//<param name="hr">HRESULT  of the error to report</param>
	void reportError(HRESULT hr);

	// Bug 267
	CXFormsConfig m_XFConfig;
	void showSplash(void);
	inline bool Configured(void) const;
	inline void Configured(bool bConfigured);

	// Insert the new-style branding in the form.
	void NeoBrandForm(void);

	// Remove the new-style branding from the form.
	void NeoDeBrandForm(void);

	// Invoke the Soft-SysTray instance for this form.
	//HRESULT InvokeDefaultSystray(void);

	// Return a pointer to the Soft-SysTray instance for this form.
	//ISysTrayIcon *DefaultSystray(void);
	HRESULT AddScriptLibrariesToViewlinkDocument(IHTMLDocument2 *pDoc2);
	HRESULT RemoveScriptLibrariesFromViewlinkDocument(IHTMLDocument2 *pDoc2);
	HRESULT put_Factory(IFactory * pFac);
	CUIImplRepository * GetUIImplRepository(void);

	// <summary>accessor function fo rm_plOwnerDocument</summary>
	//<parameter name="ppDoc">takes the returned document pointer</parameter>
	HRESULT GetOwnerDocument(IHTMLDocument2 ** ppDoc);
	// <summary>indicates whether a modal message is active right now, so that an action may be deferred until after it has returned.</summary>
	bool modalMessageActive(void);
	// <summary>When a modal message is active, this stores any actions posted after it, so that they can be invoked on return of the message.</summary><remarks>This must be the listener, not the action, in case another modal message exists in the list</remarks>
	HRESULT AddPostModalAction(IAction * pAction);
	//<summary>sets the flag to indicate that actions should now be stored rather than executed</summary>
	void activateModalMessage();
	//<summary>executes stored actions and resets the modal flag to false</summary>
	HRESULT deactivateModalMessage();
	// <summary>returns the requested interfaace of the xforms factory object in the document</summary>
	HRESULT GetElementFactory(const IID * piid, void ** ppFactory);

	// Methods for use with m_ControlsVector.
	HRESULT GetControl(const CFormControl **pp, bool bStart = false);
	HRESULT AddControl(const CFormControl *p);

	// Reinstated for bug 596
	//void LegacyFixupErrorMessage(const char * const sMessage, BSTR *pbsRetval);
	HRESULT LegacyMessage(BSTR sText, bool bNavigate = false);
	// <summary>Sets the current model for contextual evaluation of of the instance('id') XPath function</summary>
	void SetActiveModel(CImplModel * pModel);
	///<summary>
	///	Retreives a pointer to the model (ppModel) that has the instance which contans the specified node (pNode).
	///</summary>
	HRESULT findModel(IXMLDOMNode * pNode, CImplModel ** ppModel);
	///<summary>Increase the count of nested actions</summary>
	inline unsigned long IncreaseDeferredUpdateCnt();
	///<summary>Decrease the count of nested actions and when it zero run deferred update</summary>
	inline unsigned long DecreaseDeferredUpdateCnt();
	///<summary>Check whether we should defer the action until the root event handler performs 
	/// deferred  update</summary>
	inline bool IsInDeferredUpdate();
	void AddControlAwaitingFocus(CFormControl * pControl);

	void ShowTIP(void);
	void HideTIP(void);
	void ShowPIP(void);
	void HidePIP(void);

	virtual HRESULT handleEvent(DISPID eventID,VARIANT* pvarResult,DISPPARAMS* pdispparams);

	void AddDeletionListener(IDeletionListener * pListener);
	void RemoveDeletionListener(IDeletionListener * pListener);

	private:
	CFormControlList m_ControlsAwaitingFocus;
	HRESULT FocusControlAwaitingFocus();

	CComBSTRList m_lstPendingRepeats;
	CAsyncRunnerList m_AsyncRunners;
	void AwaitLegalCloseOfForm();
	HRESULT addDefaultStylesheet();
	CMSHTMLCSS3Handler * m_pCSSHandler;
	//used to store any namespace prefixes from importAdditionalNamespacePrefixes
	//	so that addDefaultStylesheet can insert them later.
	CComBSTRList m_lstNamespacePrefixesWhichCorrespondToTheXFormsNamespace;

	CMapCComBSTRToSafeArray m_mapUIChunks;
	//<value>stores a string representing an appropriate iteration wrapper for any repeat in this form. </value>
	CComBSTR m_sRepeatIterationWrapper;	
	//<value>stores the count of models yet to be in construct-done state</value>
	long m_lPendingModels;
	HRESULT burnDeadControls();
	
	// Holds the UIWapper for the UIControls
	CComBSTR m_sUIWrapper;
	int m_iUIWrapperLen;
	// Loads the m_sUIWapper with the UIWrapper from the resource.
	// Also populates global properties such as css & NamespaceDeclaration etc
	HRESULT loadUIWrapper(void);

	CTypedPtrList<CPtrList, CFormControl*> m_DeadFormControls;
	//part of the destructor, destroys controls, and removes the references.
	HRESULT reset(void);
	void destroyUIChunks();

	//holds the configuration document.
	CDOM3Document m_Config;

	//	if a fatal exception occurs, this will be set to true to stop
	//	further processing.  it aids in graceful failing and early failing.
	//	so that if an exception is encountered near the beginning of a large 
	//	form, the user does not have to sit and wait for the whole thing to
	//	load.  This property is maintained by the onFatalException and canContinue functions.
	bool m_bFatalErrorEncountered;
	//The closedown process takes some time, if it is called during startup
	//	ie. the window is closed or navigates away too soon,
	//	errors may occur.
	bool m_bShutDown;
	//maintain a running total of models that have not been fully initialised
	//	Once this gets to zero, and the document has loaded, we can begin 
	//	UIInitialize processing.
//	long m_lPendingModels;
	bool m_bDocumentLoaded;
	//This is set to true when document is loaded and there are no more elements
	//	to process.  Different to documentLoaded 
	bool m_bDocumentComplete;
	//called by onload and decrementPendingModels.  It will only
	//	run whan m_bDocumentLoaded is true and m_lPendingModels is 0
	void onDocumentComplete();

	//maintain a list of no currently open windows, so that they can be destroyed
	//	if the main window closes before the modeless dialogs.
	CTypedPtrList<CPtrList,CMessageDialog *> m_OpenMessageWindows;
	//maintain a list of no longer needed windows so that we can delete them
	//	at next opportunity.
	CTypedPtrList<CPtrList,CMessageDialog *> m_ClosingMessageWindows;
	IXPathNSResolver * m_pNSResolver;

	//	<remarks>
	//If a pointer cannot be placed in one of the above maps,
	//	one reason may be that there is a duplicate ID.  We 
	//	need to store it in order to delete it, otherwise we get
	//	a memory leak.  It may be wise to store all the heap pointers
	//	here, including those that go into the maps above.  That way we
	//	can just do one loop to run through and delete all the pointers
	//	without fear of overdelete etc.  This will require some thought,
	//	So I am just putting the Rubbish pointers in here for now.
	//	</remarks>
	CPtrList m_HeapPointers;

	CMapStringToPtr m_SubmitInfoList;

	//a list of models in the document, it maps id to the model.
	//	models are deleted from here and in turn delete
	//	their bound controls.
	CMapStringToPtr m_ModelList;
	CMapStringToPtr m_Instances;

	CMapPtrToPtr m_MapDocToModel;
	CComObject<CXFormsXPathFunctions> * m_pFuncLib;
	CComObject<CEventSink> * m_pDocEventSink;
	HRESULT modalMessage(const BSTR sText,bool bNavigate=false) const;

	CMessageDialog * m_pSplash;
	CMapPtrToPtr m_ControlContainers;

	//cache of the CSS applied to the form.
	mutable CComBSTR m_sCSS;
	// cache of the length of m_sCSS
	mutable long m_lCssLength;


	bool m_bAmAddingControls;
	CIdResolver * m_pXPathIdResolver;
	//to handle next/previous event.
	CFormControl * m_pPreviousControl;
	CFormControl * m_pCurrentControl;
	//to allow async initialisation of elements.
	long m_lPendingElements;

	//<remarks>
	//	Stores the first encountered model, which should be 
	//	the first in document order, although that is out
	//	of the control of this class.  This is to be returned by
	//	<see cref="">getModel</see> when called with null as the 
	//	string argument.
	//</remarks>
	CImplModel * m_pDefaultModel;
	//<summary>
	//	checks if there are any mustunderstand attributes on elements
	//	that we don't understand
	//</summary>
	//<param name="pbAllUnderstood">
	//	pointer to a bool which recieves false if there are any elements
	//	that we don't (and must) understand, and true if there are none.
	//</param>
	HRESULT checkMustUnderstand(bool * pbAllUnderstood);
	// Superceded by bug 267...
	//bool m_bBrandingRequired;
	//bool CheckRegistryForBrandingKeys(void);
	CList<wchar_t*, wchar_t*> m_lstRepeatsBeingWaitedFor;
	// <summary>Resolves the url of the current XForms document, and stores it in m_sCurrentURL</summary>
	HRESULT ResolveDocumentURL(void);
	HRESULT LoadScriptLibrary(IScriptEngine2 * pScript2,CString sPathToScript);
	HRESULT PrepareNewScriptLibrary(IScriptEngine ** ppLibraryToCreate);
	HRESULT AddScriptingObjectToDocument(BSTR bsScriptObjectName, IScriptEngine * pScript,IHTMLDocument2 * pDoc);
	HRESULT RemoveScriptingObjectFromDocument(BSTR bsScriptObjectName,IHTMLDocument2 * pDoc);
	HRESULT CreateScriptaculousLibrary();
	HRESULT CreateRicoLibrary();
	HRESULT CreatePanelLibrary();
	HRESULT CreateSelect1MinimalLibrary();
	CComPtr<IScriptEngine> m_pScriptaculous;
	CComPtr<IScriptEngine> m_pPanel;
	CComPtr<IScriptEngine> m_pRico;
	//<summary>Registers an onUnload handler to delete this object when the form is unloaded.</summary>
	void registerUnload();
	//<summary>creates m_pNSResolver using the declared namespaces in the current document</summary>
	HRESULT createNSResolver();
	//<summary>loads the configuration file formsplayer.xml</summary>
	void loadConfigFile();

	//<summary>
	//	retrieves the namespace declarations from MSHTML DOM and 
	//	translates them into xml text.
	//</summary>
	//<remarks>only changes the two mutables m_lNamespaceDeclaration && m_sNamespaceDeclaration</remarks>
	HRESULT serializeNamespaces(); 

	//<summary>wraps an error message so that it looks pretty when it is displayed to the user </summary>
	//<param name="sMessage">The message to fix up</param>
	//<param name="pbsRetval">pointer to a BSTR to recieve the pretty message</param>
	void fixupErrorMessage(const char * const sMessage, BSTR * pbsRetval) const;

	bool m_bConfigured, m_bBranded, m_bSystrayInvoked;

	//<summary>
	//	This was in XFormsManager, but sharing scripts across
	//	browser windows caused unexpected errors.
	//	So now it is implemented per-form.
	//</summary>
	CUIImplRepository * m_pUIImplRepository;
	CTempDocImpl *m_pDocImpl;
	CDocumentImplementationHasFeature *m_pHasFeature;
	CDocumentImplementationGetFeature *m_pGetFeature;
	CDocumentEventCreateEvent *m_pDocumentEvent;

	CComQIPtr<IHTMLDocument2> m_pOwnerDocument;

	//<summary>flag to prevent actions being invoked while a modal message is active.</summary>
	bool m_bModalMessageActive;
	//<summary>stores actions to be executed after the current modal message has closed</summary>
	CTypedPtrList<CPtrList,IAction*> m_lstPostModalActions;
	//<summary>executes the actions stored by AddPostModalAction</summary>
	HRESULT ExecutePostModalActions();
	//<summary>stores a pointer to the first xforms behaviour factory in the document</summary>
	CComQIPtr<IFactory> m_pFactory;

	// Lookup list of form controls [see bug 459]. Destruction of this list does not
	// imply detruction of the form controls contained within.
	std::vector<const CFormControl*> m_ControlsVector;
	std::vector<const CFormControl*>::size_type m_ControlsIndex;
	//<summary>
	//	Called by reportError and reportException to actually show the error to the user.
	//</summary>
	//<parameter name="sError">The text of the error message.</parameter>
	void showError(const char * const sError);
	//<summary>
	//	Inserts a message element into the document, used to 
	//	report error messages to the user.
	//</summary>
	void createErrorMessageReceptacle();
	//<summary>
	//	Factory for creating CErrorReportAction objects
	//</summary>
	CErrorReportActionFactory m_ErrorActionFactory;

	// The default per-form systray icon.
	//CComPtr<ISysTrayIcon> m_pDefaultSysTrayIcon;

	///<summary>Count of nested actions being processed. When this count becomes zero 
	///it indicates that deferred update should be performed.</summary>
	unsigned long m_ulDeferredUpdateCnt;

	IValueElementStringGenerator * m_pValueElementStringGenerator;
	HRESULT AddFormsPlayerExecutionContext();
	// Pointer to the Pen Input Panel, will always be null unless we are running on a Tablet PC.
	CComPtr<IPenInputPanel> m_pPIP;
	bool CreatePIP(void);

	// Pointer to the Tablet PC Input Panel, will always be null unless we are running on a Tablet PC.
	CComPtr<IDispatch> m_pTIP;
	HRESULT GetFactoryId(CComBSTR & sId);

	HRESULT AddCaretHidingHack();
	HRESULT CaretHidingHack(CComPtr<IHTMLEventObj2> &pEvObj);
	CComQIPtr<IHTMLElement3> m_pSecretCaretStealer;
	bool m_bPerformingCaretHack;

	void NotifyDeletionListeners();
	void FlushDeletionListeners();

	CListOfDeletionListeners m_lstDeletionListeners;

};


inline bool CXFormsXFormsElement::canContinue() const
{
	//If the form is shutting down, or a fatal error has 
	//	been encountered return false.
	return !(m_bShutDown || m_bFatalErrorEncountered);
}

inline void CXFormsXFormsElement::StartAddingControls()
{
	// Create the mutex that allows us to try looking up ids and only
	// return an error when the document is complete and there is no id.
	if(!m_bAmAddingControls)
		m_bAmAddingControls = true;
}

inline void CXFormsXFormsElement::onElementEncountered()
{
	++m_lPendingElements;

};

inline void CXFormsXFormsElement::onElementComplete()
{
	--m_lPendingElements;
}

inline bool CXFormsXFormsElement::isDocumentComplete() const
{
	return m_bDocumentComplete && !m_bFatalErrorEncountered;
}

inline HRESULT CXFormsXFormsElement::getUIWrapper(BSTR *pszWrapper) 
{
	if(!m_sUIWrapper)
		loadUIWrapper();
	m_sUIWrapper.CopyTo(pszWrapper);
	return S_OK;
};

inline int CXFormsXFormsElement::getUIWrapperLen()
{
	return m_iUIWrapperLen;
}

inline HRESULT CXFormsXFormsElement::putXPathIdentityResolver(CIdResolver *pResolver)
{
	if(m_pXPathIdResolver && pResolver)
		// This would suggest that the previous user has not finished with it yet.
		return E_FAIL;
	else {
		m_pXPathIdResolver = pResolver;
		return S_OK; 
	}
}

inline CMapStringToPtr* CXFormsXFormsElement::getModelList(void)
{
	return &m_ModelList;
}

inline CMapPtrToPtr* CXFormsXFormsElement::getControlContainers(void)
{
	return &m_ControlContainers;
}

// Superceded by bug 267...
//inline bool CXFormsXFormsElement::BrandingRequired(void) const
//{
//	return m_bBrandingRequired;
//}

inline bool CXFormsXFormsElement::Configured(void) const
{
	return m_bConfigured;
}

inline void CXFormsXFormsElement::Configured(bool bConfigured)
{
	m_bConfigured = bConfigured;
}

inline unsigned long CXFormsXFormsElement::IncreaseDeferredUpdateCnt() {
	return (++m_ulDeferredUpdateCnt);
}

inline unsigned long CXFormsXFormsElement::DecreaseDeferredUpdateCnt() {
	if(m_ulDeferredUpdateCnt) 
		// Because of the way modal messages is implemeneted we need to insure that 
		// the we've not queued events to be processed after the message has been 
		// closed.
		if(!(--m_ulDeferredUpdateCnt) && m_lstPostModalActions.IsEmpty())
			RunDeferredUpdate();
	return m_ulDeferredUpdateCnt;
}

inline bool CXFormsXFormsElement::IsInDeferredUpdate()
{
	// We should also perform deferred update if we've got queued events 
	// because  of modal messages.
	return (m_ulDeferredUpdateCnt > 0 || !m_lstPostModalActions.IsEmpty());
}

#endif // !defined(AFX_XFORMSXFORMSELEMENT_H__F6990E5B_034E_4979_94DD_B7F8BC7EB56E__INCLUDED_)
